package com.ksvip.next.components.redis;

import com.ksvip.next.components.core.constant.SystemConstants;
import com.ksvip.next.components.redis.autoconfigure.RedisConfiguration;
import com.ksvip.next.components.redis.cache.JedisCache;
import com.ksvip.next.components.redis.cache.RedisTemplateCache;
import com.ksvip.next.components.redis.lock.JedisLockService;
import com.ksvip.next.components.redis.lock.LockManager;
import com.ksvip.next.components.redis.lock.LockService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@EnableConfigurationProperties(value = { RedisConfiguration.class })
@Configuration
@ConditionalOnProperty(prefix = SystemConstants.GLOBAL, name = "redis-open", havingValue = "true")
public class RedisAutoConfiguration {

    @Bean(value = "jedisPoolManager", initMethod = "init", destroyMethod = "destory")
    public JedisPoolManager jedisPoolManager(RedisConfiguration redisConfiguration) {
        JedisPoolManager poolManager = null;
        if (StringUtils.isBlank(redisConfiguration.getZkServer())
                && StringUtils.isBlank(redisConfiguration.getRedisConfigKey())) {
            poolManager = new JedisPoolManager(redisConfiguration.getHost(), redisConfiguration.getPassword(),
                    redisConfiguration.getPort());
        } else {
            poolManager = new JedisPoolManager(redisConfiguration.getRedisConfigKey(), redisConfiguration.getZkServer(),
                    300, 40, 3000, 1000);
        }

        log.info("******load JedisPoolManager={} **********", poolManager);
        return poolManager;
    }

    @Bean(value = "jedisLockService")
    @DependsOn(value = { "jedisPoolManager" })
    public JedisLockService jedisLockService(JedisPoolManager jedisPoolManager) {
        JedisLockService lockService = new JedisLockService(jedisPoolManager);
        log.info("******load lockService **********");
        return lockService;
    }

    //    @Bean(value = "redisTemplateLockService")
    //    public RedisTemplateLockService redisTemplateLockService(RedisTemplate<String, String> redisTemplate) {
    //        RedisTemplateLockService lockService = new RedisTemplateLockService(redisTemplate);
    //        log.info("******load redisTemplateLockService **********");
    //        return lockService;
    //    }

    @Bean("redisTemplate")
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(
                Object.class);
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setStringSerializer(new StringRedisSerializer());
        log.info("******load redisTemplate **********");
        return redisTemplate;
    }

    @Bean
    @DependsOn(value = { "jedisLockService" })
    public LockManager lockManager(JedisLockService jedisLockService) {
        LockManager lockManager = new LockManager(jedisLockService);
        log.info("******load lockManager **********");
        return lockManager;
    }

    @Bean
    @DependsOn(value = { "jedisPoolManager" })
    public JedisCache JedisCache(JedisPoolManager jedisPoolManager) {
        JedisCache JedisCache = new JedisCache(jedisPoolManager);
        log.info("******load JedisCache **********");
        return JedisCache;
    }

    @Bean
    @DependsOn(value = { "redisTemplate" })
    public RedisTemplateCache redisTemplateCache(RedisTemplate<String, String> redisTemplate) {
        RedisTemplateCache redisTemplateCache = new RedisTemplateCache(redisTemplate);
        log.info("******load redisTemplateCache **********");
        return redisTemplateCache;
    }

}
